import 'dart:async';
import 'dart:io';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_sound/flutter_sound.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:flutter/services.dart';
import 'package:logger/logger.dart';

typedef RecordPermissionCallback = Future<bool> Function();
typedef RecordStartCallback = void Function();
typedef RecordEndCallback = void Function(Duration duration, String filePath);
typedef RecordPermissionPermanentlyDeniedCallback = void Function();

var logger = Logger();

class RecordButton extends StatefulWidget {
  final RecordPermissionCallback onNeedPermission;
  final RecordStartCallback onRecordStart;
  final RecordEndCallback onRecordEnd;
  final RecordPermissionPermanentlyDeniedCallback? onPermissionPermanentlyDenied;

  const RecordButton({
    Key? key,
    required this.onNeedPermission,
    required this.onRecordStart,
    required this.onRecordEnd,
    this.onPermissionPermanentlyDenied,
  }) : super(key: key);

  @override
  State<RecordButton> createState() => _RecordButtonState();
}

enum _RecordState { idle, recording, willCancel, requestingPermission }

class _RecordButtonState extends State<RecordButton> {
  _RecordState _state = _RecordState.idle;
  late FlutterSoundRecorder _recorder;
  bool _hasPermission = false;
  String? _filePath;
  DateTime? _startTime;
  Timer? _timer;
  // 将柱子数量从 10 改为 25
  List<double> _amplitudes = List.filled(_numberOfBars, _minAmplitude); // 初始化为最小高度对应的振幅
  StreamSubscription? _dbSub;

  // 定义柱子数量
  static const int _numberOfBars = 25;

  // 定义柱子基础高度和最大动态高度
  // 音柱最高高度为控件高度的一半 (44 / 2 = 22)
  // _AudioVisualizer.baseBarDisplayHeight 是柱子固定的基础高度 18
  // 所以最大动态高度部分是 22 - 18 = 4
  static const double _minAmplitude = 1.0; // 最小动态高度对应的振幅
  static const double _maxAmplitude = 4.0; // 最大动态高度对应的振幅 (22 - 18 = 4)


  @override
  void initState() {
    super.initState();
    _recorder = FlutterSoundRecorder();
    _initRecorder();
    _checkInitialPermission();
  }

  Future<void> _initRecorder() async {
    await _recorder.openRecorder();
    await _recorder.setSubscriptionDuration(Duration(milliseconds: 50));
  }

  @override
  void dispose() {
    _timer?.cancel();
    _dbSub?.cancel();
    if (_recorder.isRecording || _recorder.isPaused) {
      _recorder.stopRecorder();
    }
    _recorder.closeRecorder();
    super.dispose();
  }

  Future<void> _checkInitialPermission() async {
    var status = await Permission.microphone.status;
    _hasPermission = status.isGranted;
  }

  Future<void> _requestMicrophonePermission() async {
    if (_state != _RecordState.idle || _hasPermission) return;

    setState(() {
      _state = _RecordState.requestingPermission;
    });

    var status = await Permission.microphone.status;

    if (status.isGranted) {
      _hasPermission = true;
    } else if (status.isPermanentlyDenied) {
      if (widget.onPermissionPermanentlyDenied != null) {
        widget.onPermissionPermanentlyDenied!();
      }
      _hasPermission = false;
    } else {
      _hasPermission = await widget.onNeedPermission();
      if (!_hasPermission) {
        var finalStatusAfterRequest = await Permission.microphone.status;
        if(finalStatusAfterRequest.isGranted) _hasPermission = true;
        if(finalStatusAfterRequest.isPermanentlyDenied && widget.onPermissionPermanentlyDenied != null){
          widget.onPermissionPermanentlyDenied!();
        }
      }
    }

    setState(() {
      _state = _RecordState.idle;
      _amplitudes = List.filled(_numberOfBars, _minAmplitude); // 回到 idle 状态时重置为最小振幅
    });
  }


  Future<void> _startRecordingInternal() async {
    if (!_hasPermission || _state != _RecordState.idle) {
      return;
    }

    _filePath = await _getTempFilePath();
    try {
      await _recorder.startRecorder(
        toFile: _filePath,
        codec: Codec.aacADTS,
        sampleRate: 44100,
        numChannels: 1,
      );
      _startTime = DateTime.now();
      setState(() {
        _state = _RecordState.recording;
      });
      widget.onRecordStart();
      _startDbListener(); // 启动音量监听
    } catch (e) {
      logger.e("录音启动失败: $e");
      setState(() {
        _state = _RecordState.idle;
        _amplitudes = List.filled(_numberOfBars, _minAmplitude); // 启动失败重置动画
      });
    }
  }


  Future<String> _getTempFilePath() async {
    final dir = await getTemporaryDirectory();
    return '${dir.path}/record_${DateTime.now().millisecondsSinceEpoch}.aac';
  }

  void _startDbListener() {
    _dbSub?.cancel();
    _dbSub = _recorder.onProgress?.listen((event) {
      if (event.decibels != null) {
        final double db = event.decibels!.clamp(0.0, 120.0);

        // 将 0-120 分贝值映射到 _minAmplitude 到 _maxAmplitude 的动态高度振幅范围
        final double dynamicAmplitude = _minAmplitude + (db / 120.0) * (_maxAmplitude - _minAmplitude);

        // 使用映射后的动态高度振幅生成柱状图数据
        final List<double> bands = List.generate(_numberOfBars, (i) {
          // 基础动态高度振幅 + 波动（使动画更生动）
          final double variation = sin((i / _numberOfBars * 2 * pi + DateTime.now().millisecondsSinceEpoch / 150.0) * 1.0) * (dynamicAmplitude * 0.5);

          // 单个柱子的振幅是 动态高度振幅 + 波动
          double currentAmplitude = dynamicAmplitude + variation;

          // 确保振幅在定义的范围内
          currentAmplitude = currentAmplitude.clamp(_minAmplitude, _maxAmplitude);

          return currentAmplitude;
        });
        setState(() {
          _amplitudes = bands;
        });
      } else {
        // 如果 decibels 为 null，让柱子缓慢衰减到最小振幅
        setState(() {
          _amplitudes = _amplitudes.map((amp) => max(_minAmplitude, amp * 0.9)).toList(); // 缓慢衰减
        });
      }
    }, onError: (e) {
      logger.e("onProgress stream error: $e");
      _stopRecord(cancel: true);
    }, onDone: () {
      logger.i("onProgress stream done.");
    });
  }


  void _stopRecord({bool cancel = false}) async {
    if (_state == _RecordState.idle || _state == _RecordState.requestingPermission) return;

    _timer?.cancel();
    _dbSub?.cancel();
    if (_recorder.isRecording || _recorder.isPaused) {
      await _recorder.stopRecorder();
    }

    final duration = (_startTime != null) ? DateTime.now().difference(_startTime!) : Duration.zero;
    final filePath = _filePath;

    setState(() {
      _state = _RecordState.idle;
      _amplitudes = List.filled(_numberOfBars, _minAmplitude); // 停止后重置动画到最小振幅
    });

    if (!cancel && filePath != null && File(filePath).existsSync()) {
      widget.onRecordEnd(duration, filePath);
    } else if (filePath != null && File(filePath).existsSync()) {
      try {
        await File(filePath).delete();
      } catch (e) {
        logger.e("删除临时文件失败: $e");
      }
    }
    _filePath = null;
    _startTime = null;
  }

  void _onPointerDown(PointerDownEvent event) async {
    if (_state == _RecordState.idle) {
      HapticFeedback.lightImpact();
      if (_hasPermission) {
        _startRecordingInternal();
      } else {
        var status = await Permission.microphone.status;

        if (status.isPermanentlyDenied) {
          if (widget.onPermissionPermanentlyDenied != null) {
            widget.onPermissionPermanentlyDenied!();
          }
        } else {
          _requestMicrophonePermission();
        }
      }
    }
  }

  void _onPointerUp(PointerUpEvent event) {
    if (_state == _RecordState.recording) {
      _stopRecord(cancel: false);
    } else if (_state == _RecordState.willCancel) {
      _stopRecord(cancel: true);
    }
  }

  void _onPointerMove(PointerMoveEvent event, RenderBox box) {
    if (_state == _RecordState.recording || _state == _RecordState.willCancel) {
      final local = box.globalToLocal(event.position);
      final double verticalMovement = local.dy;

      final double cancelThreshold = -50.0;

      if (verticalMovement < cancelThreshold) {
        if (_state == _RecordState.recording) {
          setState(() {
            _state = _RecordState.willCancel;
          });
          HapticFeedback.lightImpact();
        }
      } else {
        if (_state == _RecordState.willCancel) {
          setState(() {
            _state = _RecordState.recording;
          });
          HapticFeedback.lightImpact();
        }
      }
    }
  }


  @override
  Widget build(BuildContext context) {
    final isRecording = _state == _RecordState.recording;
    final isCancel = _state == _RecordState.willCancel;
    final isRequestingPermission = _state == _RecordState.requestingPermission;

    // 定义颜色
    final Color idleBorderColor = Color(0xFF49D994);
    final Color recordingColor = Color(0xFF21A675);
    final Color cancelColor = Color(0xFFFF4545);
    final Color idleBackgroundColor = Colors.white;


    final bool enableListener = !isRequestingPermission;

    return Listener(
      onPointerDown: enableListener ? _onPointerDown : null,
      onPointerUp: enableListener ? _onPointerUp : null,
      onPointerCancel: enableListener ? (_) => _stopRecord(cancel: true) : null,
      onPointerMove: enableListener ? (event) {
        final box = context.findRenderObject() as RenderBox;
        _onPointerMove(event, box);
      } : null,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          if (isRecording || isCancel)
            Padding(
              padding: const EdgeInsets.only(bottom: 8.0),
              child: Text(
                isCancel ? "松开取消" : "松手创建，上移取消",
                style: TextStyle(
                  color: isCancel ? Colors.red : Colors.black54,
                  fontSize: 16,
                ),
              ),
            ),
          AnimatedContainer(
            duration: Duration(milliseconds: 150),
            height: 44,
            width: 320,
            // 使用 BoxDecoration 设置背景色、边框和圆角
            decoration: BoxDecoration(
              color: isRecording
                  ? recordingColor
                  : isCancel
                  ? cancelColor
                  : idleBackgroundColor, // idle 和 requestingPermission 都是白色背景
              borderRadius: BorderRadius.circular(44),
              border: isRecording || isCancel
                  ? null // 录音和取消状态无边框
                  : Border.all( // Idle 状态有边框
                color: idleBorderColor, // 边框颜色
                width: 0.5, // 边框宽度
              ),
              // **在 Idle 状态下添加 boxShadow**
              boxShadow: !isRecording && !isCancel // 只在 idle 状态下显示阴影
                  ? [
                BoxShadow(
                  color: idleBorderColor.withOpacity(0.1), // 发光颜色，可以调整透明度
                  blurRadius: 8.0, // 模糊半径，控制发光范围
                  spreadRadius: 2.0, // 扩展半径，控制阴影大小
                  offset: Offset(0, 0), // 偏移量，(0,0) 表示中心发光
                ),
              ]
                  : null, // 其他状态没有阴影
            ),
            child: isRecording || isCancel
                ? Center(
              child: _AudioVisualizer(
                amplitudes: _amplitudes,
                color: Colors.white, // 音柱颜色保持白色
              ),
            )
                : Center(
              child: Text(
                isRequestingPermission ? "请授予权限" : "按住录制",
                style: TextStyle(
                  color: Colors.black87,
                  fontSize: 18,
                  fontWeight: FontWeight.w500,
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

class _AudioVisualizer extends StatelessWidget {
  final List<double> amplitudes;
  final Color color;

  const _AudioVisualizer({
    Key? key,
    required this.amplitudes,
    required this.color,
  }) : super(key: key);

  // 柱子的基础高度，这个高度是固定的，与动画无关
  static const double baseBarDisplayHeight = 4.0;


  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      crossAxisAlignment: CrossAxisAlignment.center,
      mainAxisSize: MainAxisSize.min,
      children: List.generate(amplitudes.length, (i) {
        final double amp = amplitudes[i];
        // 单个柱子的最终高度 = 基础高度 + 振幅（动态高度部分）
        final double barHeight = baseBarDisplayHeight + amp;

        return Padding(
          padding: const EdgeInsets.symmetric(horizontal: 1.5),
          child: AnimatedContainer(
            duration: Duration(milliseconds: 80),
            width: 2,
            height: barHeight,
            decoration: BoxDecoration(
              color: color,
              borderRadius: BorderRadius.circular(3),
            ),
          ),
        );
      }),
    );
  }
}